﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using BattleShips.Common;
using BattleShips.GameServers;
using BattleShips.GameServers.BattleShipsGame;

namespace TestServer {
    class GameClient : IPlayer {
        private TcpClient tcpClient;
        private GameServer gameServer;

        public uint IdPlayer { get; set; }
        public string Username { get; set; }
        public string PlayerStatus { get; set; }
        public string Permission { get; set; }
        public string InRoomName { get; set; }
        public bool Playing { get; set; }
        public string Presence { get; set; }
        public uint InRoomId { get; set; }
        public ClientGameState clientGameState { get; set; }

        public void InitializeClientProp() {
            this.IdPlayer = 0;
            this.Username = string.Empty;
            this.PlayerStatus = string.Empty;
            this.Permission = string.Empty;
            this.InRoomName = string.Empty;
            this.InRoomId = 0;
            this.Playing = false;
            this.Presence = string.Empty;
            this.clientGameState = new ClientGameState();
        }

        public GameClient(GameServer server, TcpClient tcpClient) {
            this.gameServer = server;
            this.tcpClient = tcpClient;

            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(tcpClient);
        }
        private void HandleClientComm(object client) {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;
            while (true) {
                bytesRead = 0;
                try {
                    bytesRead = clientStream.Read(message, 0, 4096);
                } catch {
                    break;
                }
                if (bytesRead == 0) {
                    break;
                }
                ASCIIEncoding encoder = new ASCIIEncoding();
                Console.WriteLine(encoder.GetString(message, 0, bytesRead));

                HandleCommand(encoder.GetString(message, 0, bytesRead));
            }

            tcpClient.Close();
        }
        private void HandleCommand(string command) {
            try {
                GameCommandParser parser = new GameCommandParser();
                Command cmd = parser.Parse(command);

                ICommandRunner runner = CommandRunnerRegistry.GetCommandRunner(cmd.CommandName);
                string payload = runner.RunCommand(cmd, this, gameServer);

                Response response = new Response();

                response.CommandName = cmd.CommandName;
                response.Code = 0;
                response.Payload = payload;

                this.SendMessage(response.ToString());

            } catch (ParseException ex) {
                this.SendMessage(new Response() { Code = 1, CommandName = "_error_", Payload = ex.Message }.ToString());
            } catch (KeyNotFoundException) {
                this.SendMessage(new Response() { Code = 2, CommandName = "_error_" }.ToString());
            } catch (CommandException ex) {
                this.SendMessage(new Response() { Code = ex.ErrorCode, CommandName = ex.CommandName, Payload = ex.Message }.ToString());
            } catch (Exception ex) {
                this.SendMessage(new Response() { Code = 999, CommandName = "_error_", Payload = ex.Message }.ToString());
            }
        }
        public void SendMessage(string message) {
            ASCIIEncoding encoder = new ASCIIEncoding();
            this.tcpClient.GetStream().Write(encoder.GetBytes(message), 0, message.Length);
        }
    }
}
